<?php

/**
 * Classe per la manipolazione delle immagini tramite le librerie ImageMagick
 *
 * @author Fabrizio Filieri
 */
class Image
{
	/**
	 * Allineamento in alto a sinistra
	 */
	const NORTH_WEST					= "NorthWest";

	/**
	 * Allineamento in alto
	 */
	const NORTH							= "North";

	/**
	 * Allineamento in alto a destra
	 */
	const NORTH_EAST					= "NorthEast";

	/**
	 * Allineamento a sinistra
	 */
	const WEST							= "West";

	/**
	 * Allineamento al centro
	 */
	const CENTER						= "Center";

	/**
	 * Allineamento a destra
	 */
	const EAST							= "East";

	/**
	 * Allineamento in basso a sinistra
	 */
	const SOUTH_WEST					= "SouthWest";

	/**
	 * Allineamento in basso
	 */
	const SOUTH							= "South";

	/**
	 * Allineamento in basso a destra
	 */
	const SOUTH_EAST					= "SouthEast";

	/**
	 * Ridimensionamento proporzionale
	 */
	const RESIZE_PROPORTIONAL			= 1;

	/**
	 * Ridimensionamento fisso
	 */
	const RESIZE_FIXED					= 2;

	private $filename;
	private $originalWidth;
	private $originalHeight;

	/**
	 * Larghezza dell'immagine
	 * @var int larghezza dell'immagine
	 */
	public $width;

	/**
	 * L'altezza dell'immagine
	 * @var int altezza dell'immagine
	 */
	public $height;

	/**
	 * La qualità dell'immagine. Di default è impostata a 90. Il valore massimo è 100.
	 * @var int qualità
	 */
	public $quality						= 90;

	/**
	 * Tipo di ridimensionamento, Può assumere i valori RESIZE_PROPORTIONAL e RESIZE_FIXED. Di default
	 * è impostato su RESIZE_PROPORTIONAL.
	 * @var RESIZE_TYPE tipo di ridimensionamento
	 */
	public $resizeType					= Image::RESIZE_PROPORTIONAL;

	/**
	 * Flag per indicare se durante il ridimensionamento l'immagine puà essere ingrandita. Di default
	 * è impostata su false, ossia l'immagine non viene allargata se più piccola delle dimensioni impostate.
	 * Se si intende fare in modo che l'immagine si possa espandere, impostare il valore su true.
	 * @var boolean true se si intende far in modo che un'immagine durante il ridimensionamento possa allargarsi,
	 * false altrimenti
	 */
	public $larger						= false;

	/**
	 * Ascissa del vertice in alto a sinistra, in cui cominciare il taglio.
	 * @var int  ascissa del vertice in alto asinistra del taglio
	 */
	public $cropX						= 0;

	/**
	 * Ordinata del vertice in alto a sinistra in cui cominciare il taglio.
	 * @var int ordinata del vertice in alto a sinistra del taglio
	 */
	public $cropY						= 0;

	/**
	 * La larghezza del taglio.
	 * @var int la larghezza del taglio
	 */
	public $cropWidth					= 0;

	/**
	 * L'altezza del taglio.
	 * @var int l'altezza del taglio
	 */
	public $cropHeight					= 0;

	/**
	 * Imposta la gravità per i ridimensionamenti. Di default la gravità è impostata sull'angolo in
	 * alto a sinistra.
	 * 
	 * @var CONST Controllare i valori delle costanti di Image
	 */
	public $gravity						= Image::NORTH_WEST;

	/**
	 * La rotazione in senso orario, ed in gradi, dell'immagine. In caso la rotazione crei nuove zone di immagini,
	 * esse verranno riepite con un colore di background. Tale colore di default è bianco.
	 * 
	 * @var int rotazione in gradi da assegnare all'immagine
	 */
	public $rotate						= null;

	/**
	 * Il colore di sfondo dell'immagine. I formati accettati per il colore sono i seguenti:
	 * #RGB (espanso in RRGGBB)
	 * #RRGGBB
	 * #RRGGBBAA (il canale AA indica la trasparenza 00 è completamente trasparente, FF è completamente opaco)
	 *
	 * Di dafault il colore di sfondo è il bianco opaco.
	 * 
	 * @var string colore da assegnare allo sfondo dell'immmagine nel formato RRGGBBAA
	 */
	public $background					= null;

	/**
	 * Indica il valore del tono seppia da assegnare all'immagine. Lasciare null per non attivare il filtro.
	 * Un valore comune e ottimale è un valore pari ad 80. Può assumere valori da 0 a 99.
	 *
	 * @var int il valore del tono di seppia
	 */
	public $sepia						= null;

	/**
	 * Trasforma l'immagine in bianco e nero. Impostarl a true per renderla in bianco e nero, false o null per lasciarla nella
	 * colorazione originale.
	 *
	 * @var boolean true per rendere l'immagine in bianco e nero
	 */
	public $blackwhite					= null;

	/**
	 * Applica un filtro colorize all'immagine con un colore pieno nel formato:
	 * #RGB
	 * #RRGGBB
	 * Lasciare a null per non applicare alcun filtro.
	 *
	 * @var string la stringa con il colore da applicare al filtro
	 */
	public $colorize					= null;


	/**
	 * Apre l'immagine per le successive manipolazioni e legge le sue informazioni.
	 * In caso di errore in lettura dell'immagine o file inesistente, genera un'eccezione.
	 */
	public function __construct($filename)
	{
		$this->filename = $filename;

		if (!file_exists($filename))
			throw new Exception("FILE NOT FOUND: " . $filename );

		// recupero informazioni sulla dimensione
		$output = "";
		exec("identify -ping -format '%wx%h' " . $this->filename, $output);

		if(!isset($output[0]))
			throw new Exception("Error reading image data: " . $filename);

		$size = explode("x", $output[0]);

		$this->width = $size[0];
		$this->height = $size[1];
		$this->originalWidth = $this->width;
		$this->originalHeight = $this->height;
	}


	/*public function save()
	{

	}*/

	/**
	 * Salva l'immagine con nome, in base ai parametri impostati.
	 *
	 * @param string $filename il nome del file su cui salvare l'immagine
	 */
	public function saveAs($filename)
	{
		// 	exec("convert ".$filesrc." -gravity ".$gravity." -crop ".$width."x".$height."+".$x."+".$y." +repage ".$fileout);
		// larger	exec("convert ".$filesrc." -resize ".$width."x".$height." ".$fileout);
		// exec("convert ".$filesrc." -resize ".$width."x".$height."\> ".$fileout);

		$option = "-quality ".$this->quality." ";

		if ($this->cropWidth != 0 && $this->cropHeight != 0)
		{
			$option.= "-gravity ".$this->gravity." -crop ".$this->cropWidth."x".$this->cropHeight."+".$this->cropX."+".$this->cropY." +repage ";
		}

		if ($this->blackwhite === true)
		{
			$option.= " -colorspace Gray ";
		}

		if ($this->colorize != null)
		{
			$option.= " -fill \"".$this->colorize."\" -tint 100 ";
		}

		if ($this->sepia != null)
		{
			$option.= " -sepia-tone ".$this->sepia."% ";
		}

		if ($this->background != null)
		{
			$option.=" -background \"".$this->background."\" ";
		}

		if ($this->rotate != null)
		{
			$option.= " -rotate ".$this->rotate." ";
		}

		if ($this->width != $this->originalWidth || $this->height != $this->originalHeight)
		{
			$option.= "-resize ".$this->width."x".$this->height;
			if ($this->resizeType == Image::RESIZE_PROPORTIONAL)
			{
				if ($this->larger)
					$option.= " ";
				else
					$option.= "\> ";
			}
			else if ($this->resizeType == Image::RESIZE_FIXED)
			{
				$option.= "\! ";
			}
		}

		$command = "convert ".$this->filename." ".$option." ".$filename;
		exec($command);
		//echo "<br>".$command."<br>";
	}

	/**
	 * Ritorna la larghezza dell'immaginr originale
	 * @return int la larghezza dell'immagine originale
	 */
	public function getOriginalWidth()
	{
		return $this->originalWidth;
	}

	/**
	 * Ritorna l'altezza dell'immagine originale.
	 * @return int l'altezza dell'immagine originale
	 */
	public function getOriginalHeight()
	{
		return $this->originalHeight;
	}

}
?>
